package com.atixaodei.demo;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;


public class NettyBasicServerExample {

    /**
     * 开发一个主从多reactor多线程模型的服务
     * @param args
     */
    public static void main(String[] args) {
        // 创建两个EventLoopGroup
        //主线程主：专门负责用来接收连接，可以理解为处理accept事件，一般boss线程一般设置一个线程设置，设置多个也只会用到一个
        EventLoopGroup bossGroup=new NioEventLoopGroup(1);
        //表示工作线程组(register)：处理子任务，除了accept之外的其他事件
        // worker线程通常要根据服务器调优，如果不写默认是就是cpu的两倍
        EventLoopGroup workGroup=new NioEventLoopGroup(4);
        //构建Netty Server的API，服务器要启动，需要创建 ServerBootstrap
        // 这个类netty把nio的模板代码都已经封装好了
        ServerBootstrap bootstrap=new ServerBootstrap();
        //Bootstrap 配置boss和worker线程
        bootstrap.group(bossGroup,workGroup)
                //指定epoll模型 配置server的通道，相当于NIO中的ServersocketChannel
                .channel(NioServerSocketChannel.class)
                // childHandler表示给worker那些线程配置了一个处理器
                //具体的工作处理类,负责处理相关SocketChannel的IO就绪事件
                // 配置初始化channel，也就是给worker线程配置对应的handler，当收到客户端的请求时，分配给指定的handler处理
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        //心跳的hander
                        //编解码
                        //协议处理
                        //消息处理
                        ch.pipeline()
                                // 添加handler，也就是具体的IO事件处理器
                                .addLast("h1",new NormalMessageHandler())
                        .addLast("h2",new ChannelInboundHandlerAdapter(){
                            @Override
                            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                System.out.println("收到消息------------第二处理器");
                            }
                        }); //处理IO事件
                    }
                });
        try {
            // 由于默认情况下是NIO异步非阻塞，所以绑定端口后，通过sync()方法阻塞直到连接建立
            // 绑定端口并同步等待客户端连接（sync方法会阻塞，直到整个启动过程完成）
            // 同步阻塞等到客户端连接
            ChannelFuture channelFuture=bootstrap.bind(8080).sync();
            System.out.println("Netty Server Started Success:listener port:8080");
            // 同步等到服务端监听端口关闭
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            //释放线程资源
            workGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
}
